package com.jike.shop.cloud.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jike.shop.cloud.entity.Payment;
import com.jike.shop.cloud.mapper.PaymentMapper;
import com.jike.shop.cloud.mq.MQProducer;
import com.jike.shop.cloud.notify.AlipayResultNotify;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Xiang Zheng
 */
@RestController
@Slf4j
public class PaymentController {
    public static final String NOTIFY_KEY = "notify:";
    @Resource
    private PaymentMapper paymentMapper;
    @Autowired
    private MQProducer mqProducer;
    @Autowired
    private StringRedisTemplate redisTemplate;
    public static final String SUCCESS = "SUCCESS";
    @RequestMapping("/alipay/resultNotify")
    public String aliPayResultNotify(@RequestParam Map<String, String> params) {
        AlipayResultNotify notify = JSON.parseObject(JSON.toJSONString(params), AlipayResultNotify.class);
        String outTradeNo = notify.getOutTradeNo();
        String key = NOTIFY_KEY + notify.getNotifyId();
        String value = UUID.randomUUID().toString();
        boolean lockSuccess = Optional.ofNullable(redisTemplate.opsForValue().setIfAbsent(key, value, 10, TimeUnit.MINUTES)).orElse(false);
        if (!lockSuccess) {
            return SUCCESS;
        }
        try {
            // 只有成功的场景会收到异步异步通知
            setPaymentSuccess(outTradeNo);
        } finally {
            redisTemplate.delete(key);
        }
        return SUCCESS;

    }


    @RequestMapping("/wechat/resultNotify")
    public String wechatResultNotify() {
        // 只有成功的场景会收到异步异步通知
        return SUCCESS;
    }

    private void setPaymentSuccess(String transactionNo) {
        Payment payment = paymentMapper.selectOne(Wrappers.lambdaQuery(Payment.class)
                .eq(Payment::getTransactionNo, transactionNo)
        );
        if (payment == null) {
            log.warn("cannot find transaction, transactionNo:{}", transactionNo);
            return;
        }
        int status = payment.getStatus();
        if (Payment.STATE_ACTING != status) {
            log.warn("payment status abnormal, transactionNo:{}, status:{}", transactionNo, status);
            return;
        }
        long id = payment.getId();
        int rows = paymentMapper.update(new Payment(), Wrappers.lambdaUpdate(Payment.class)
                .set(Payment::getStatus, Payment.STATE_SUCCESS)
                .eq(Payment::getId, id)
        );
        if (rows != 1) {
            // in case of concurrent changing status to success
            mqProducer.sendPaymentStatusChangedMessage(id, Payment.STATE_SUCCESS);
        }
    }
}
